package org.example.controller;

import com.google.common.util.concurrent.RateLimiter;
import lombok.AllArgsConstructor;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.InetSocketAddress;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 *
 **/
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/pong")
public class PongController {

//    private final RateLimiter rateLimiter;

//    @GetMapping
//    public Mono<String> pong(ServerWebExchange exchange) {
//        final ServerHttpRequest request = exchange.getRequest();
//        final InetSocketAddress remoteAddress = request.getRemoteAddress();
//
//        if (shouldLimit()) {
//            log.info("Received request from [hostName: {}, port: {},result: {}]", remoteAddress.getHostName(),remoteAddress.getPort(),HttpStatus.TOO_MANY_REQUESTS);
//            return Mono.error(new ResponseStatusException(HttpStatus.TOO_MANY_REQUESTS, "Too Many Requests"));
//        }
//        log.info("Received request from [hostName: {}, port: {},result: World]", remoteAddress.getHostName(),remoteAddress.getPort());
//        return Mono.just("World");
//    }
//
//    public boolean shouldLimit() {
//        return !rateLimiter.tryAcquire();
//    }

    private final ConcurrentHashMap<Long, AtomicInteger> rateLimiter = new ConcurrentHashMap<>();

    @GetMapping()
    public Mono<ResponseEntity<String>> pong(@RequestHeader(value = "X-Ping-Service-Name", required = false) String pingServiceName) {
        long second = System.currentTimeMillis() / 1000;
        rateLimiter.computeIfAbsent(second, k -> new AtomicInteger(0));
        AtomicInteger counter = rateLimiter.get(second);

        if (counter.incrementAndGet() > 1) {
            log.info("Received [{}]  Request,response result: {}]", pingServiceName, HttpStatus.TOO_MANY_REQUESTS);
            return Mono.just(new ResponseEntity<>(HttpStatus.TOO_MANY_REQUESTS));
        }
        log.info("Received [{}]  Request, response result: World]", pingServiceName);
        return Mono.just(new ResponseEntity<>("World", HttpStatus.OK));
    }
}
